import js from '@eslint/js'
import globals from 'globals'
import tseslint from 'typescript-eslint'
import pluginVue from 'eslint-plugin-vue'

export default tseslint.config(
  {
    // 忽略配置：指定 ESLint 应该忽略的文件和目录
    ignores: [
      // 构建输出目录
      'dist',
      'build',
      'output',

      // 依赖目录
      'node_modules',

      // 压缩文件
      '*.min.js',
      '*.min.css',

      // 构建工具生成的文件
      '/public/build/',
      '/.nuxt/',
      '/.next/',

      // 测试相关
      'coverage/',
      'cypress/screenshots/',
      'cypress/videos/',

      // 日志文件
      '*.log',

      // 环境配置文件
      '.env*',
      '!.env.example',

      // IDE 和编辑器文件
      '.vscode/',
      '.idea/',
      '*.swp',
      '*.swo',

      // OS 生成的文件
      '.DS_Store',
      'Thumbs.db',

      // Git 相关
      '.git/',
      '.gitignore',

      // 其他常见忽略项
      '.tmp/',
      'temp/',
      '.cache/',
    ],
  },
  {
    // 基础配置：适用于所有 JavaScript、TypeScript 和 Vue 文件
    files: ['**/*.{js,mjs,cjs,ts,mts,cts,vue}'],
    languageOptions: {
      ecmaVersion: 2021, // 支持 ECMAScript 2021 语法
      sourceType: 'module', // 使用 ES 模块语法
      globals: {
        // 合并 Node.js、浏览器和 ES2021 环境的全局变量
        ...globals.node,
        ...globals.browser,
        ...globals.es2021,
      },
    },
    rules: {
      // 代码风格规则

      // 分号规则
      semi: ['error', 'never'], // 禁止使用分号

      // 缩进规则
      indent: ['error', 4, { SwitchCase: 1 }], // 使用 4 个空格缩进，switch case 缩进 1 级

      // 空格规则
      'no-multi-spaces': 'error', // 禁止多个连续空格
      'space-unary-ops': ['error', { words: true, nonwords: false }], // 一元操作符前后空格规则
      'space-infix-ops': 'error', // 中缀操作符周围需要空格
      'space-before-blocks': ['error', 'always'], // 代码块前必须有空格
      'no-mixed-spaces-and-tabs': 'error', // 禁止混用空格和制表符
      'no-whitespace-before-property': 'error', // 属性名前不能有空格
      'space-in-parens': ['error', 'never'], // 括号内不允许空格

      // 空行规则
      'no-multiple-empty-lines': ['error', { max: 1 }], // 最多允许一个空行
      'no-trailing-spaces': 'error', // 禁止行尾空格
      'no-irregular-whitespace': 'error', // 禁止不规则空白符

      // 逗号规则
      'comma-dangle': ['error', 'never'], // 禁止末尾逗号
      'comma-style': ['error', 'last'], // 逗号风格：换行时在行尾
      'comma-spacing': ['error', { before: false, after: true }], // 逗号前后空格规则

      // 括号规则
      'array-bracket-spacing': ['error', 'never'], // 数组括号内不允许空格
      'object-curly-spacing': ['error', 'never'], // 对象括号内不允许空格

      // 其他格式规则
      'max-len': ['error', { code: 120 }], // 行最大长度 120 字符
      'operator-linebreak': ['error', 'before'], // 运算符换行时放在行首
      'no-extra-semi': 'error', // 禁止多余的分号
      curly: ['error', 'all'], // 控制结构必须使用大括号
      'key-spacing': ['error', { beforeColon: false, afterColon: true }], // 对象键值冒号前后空格规则
      'semi-spacing': ['error', { before: false, after: true }], // 分号前后空格规则

      // 命名规则
      camelcase: ['warn', { properties: 'always' }], // 强制使用驼峰命名
      'new-cap': ['error', { newIsCap: true, capIsNew: false }], // 构造函数首字母大写

      // 注释规则
      'spaced-comment': ['error', 'always'], // 注释后必须有空格
      'no-inline-comments': 'error', // 禁止行内注释

      // 最佳实践
      eqeqeq: ['error', 'always', { null: 'ignore' }], // 强制使用 === 和 !==
      'no-else-return': ['warn', { allowElseIf: false }], // return 后禁止使用 else
      'no-loop-func': 'error', // 禁止在循环中创建函数
      'no-implicit-coercion': ['warn', { allow: ['!!'] }], // 禁止隐式类型转换
      radix: ['error', 'always'], // parseInt 必须指定进制
      'no-array-constructor': 'error', // 禁止使用 Array 构造函数
      'no-eval': 'error', // 禁止使用 eval
      'no-var': 'warn', // 建议使用 let/const 而非 var
      'prefer-const': 'warn', // 建议对未重新赋值的变量使用 const
      'prefer-destructuring': ['warn', { object: true, array: false }], // 建议使用解构赋值
      'prefer-template': 'warn', // 建议使用模板字符串
      'template-curly-spacing': ['error', 'never'], // 模板字符串花括号内不允许空格
      'no-duplicate-imports': 'error', // 禁止重复导入

      // 复杂度控制
      'max-params': ['warn', 6], // 函数参数最多 6 个
    },
  },

  // 扩展 JavaScript 推荐规则
  js.configs.recommended,

  // 扩展 TypeScript 推荐规则，仅应用于 TypeScript 文件
  ...tseslint.configs.recommended.map((config) => ({
    ...config,
    files: ['**/*.{ts,mts,cts,vue}'],
  })),

  // 扩展 Vue 推荐规则
  ...pluginVue.configs['flat/essential'],

  {
    // Vue 文件特定配置
    files: ['**/*.vue'],
    languageOptions: {
      parserOptions: {
        parser: tseslint.parser, // 为 Vue 文件指定 TypeScript 解析器
      },
    },
  },
  //
  // {
  //   // Cypress 测试文件配置
  //   files: [ 'cypress/e2e/**/*.{cy,spec}.{js,ts,jsx,tsx}' ],
  //   plugins: {
  //     cypress: eslintPluginCypress // 引入 Cypress 插件
  //   },
  //   rules: {
  //     ...eslintPluginCypress.configs.recommended.rules // 使用 Cypress 推荐规则
  //   }
  // },

  {
    // 全局变量定义：为 Vue 3 Composition API 定义全局变量
    files: ['**/*.{js,ts,vue}'],
    languageOptions: {
      globals: {
        withDefaults: 'readonly', // Vue 3 宏函数
        defineExpose: 'readonly', // Vue 3 宏函数
        defineEmits: 'readonly', // Vue 3 宏函数
        defineProps: 'readonly', // Vue 3 宏函数
      },
    },
  },

  {
    // TypeScript 特定规则
    files: ['**/*.{ts,tsx,vue}'],
    rules: {
      '@typescript-eslint/no-unused-vars': 'error', // 禁止未使用的变量
      '@typescript-eslint/explicit-module-boundary-types': 'off', // 允许省略函数返回类型
    },
  },

  {
    // 函数长度限制：仅对 JS/TS 文件应用
    files: ['**/*.{js,ts}'],
    rules: {
      'max-lines-per-function': [
        'warn',
        {
          max: 50, // 函数最大行数 50 行
          skipComments: true, // 忽略注释行
          skipBlankLines: true, // 忽略空行
          IIFEs: true, // 对立即调用函数表达式应用规则
        },
      ],
    },
  },

  {
    // 限制特定语法使用
    files: ['**/*.{js,ts,vue}'],
    rules: {
      'no-restricted-syntax': [
        'warn',
        {
          selector: "BinaryExpression[operator='instanceof']",
          message: "Use 'instanceof' for object type detection.", // 不建议使用 instanceof 检测对象类型
        },
        {
          selector: "BinaryExpression[operator='typeof']",
          message: "Use 'typeof' for type detection.", // 不建议使用 typeof 检测类型
        },
        {
          selector: "CallExpression[callee.name='parseInt']",
          message:
            'Use Math.floor, Math.round, or Math.ceil instead of parseInt to remove decimal points.', // 不建议使用 parseInt 移除小数点
        },
      ],
    },
  },
)
